package main

import (
	"fmt"
	"testing"
)

//Target 是适配的目标接口
type Target interface {
	Request() string
}

//Adaptee 是被适配的目标接口
type Adaptee interface {
	SpecificRequest() string
}

//NewAdaptee 是被适配接口的工厂函数
func NewAdaptee() Adaptee {
	return &adapteeImpl{}
}

//AdapteeImpl 是被适配的目标类
type adapteeImpl struct{}

//SpecificRequest 是目标类的一个方法
func (*adapteeImpl) SpecificRequest() string {
	return "adaptee method"
}

//NewAdapter 是Adapter的工厂函数
func NewAdapter(adaptee Adaptee) Target {
	return &adapter{
		Adaptee: adaptee,
	}
}

//Adapter 是转换Adaptee为Target接口的适配器
type adapter struct {
	Adaptee
}

//Request 实现Target接口
func (a *adapter) Request() string {
	return a.SpecificRequest()
}

var expectt = "adaptee method"

func main() {
	t := testing.T{}
	adaptee := NewAdaptee()       // 创建一个被适配的目标
	target := NewAdapter(adaptee) // 将目标转换成为适配器
	res := target.Request()       // 通过适配器执行了被适配的目标的方法
	if res != expectt {
		t.Fatalf("expect: %s, actual: %s", expectt, res)
	} else {
		fmt.Println(res)
	}
}

// 目标：通过适配器执行了被适配的目标的方法

/*

适配器模式

适配器模式（Adapter）的定义如下：
	将一个类的接口转换成客户希望的另外一个接口，使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
	适配器模式分为类结构型模式和对象结构型模式两种，前者类之间的耦合度比后者高，且要求程序员了解现有组件库中的相关组件的内部结构，所以应用相对较少些。

该模式的主要优点如下：
	客户端通过适配器可以透明地调用目标接口。
	复用了现存的类，程序员不需要修改原有代码而重用现有的适配者类。
	将目标类和适配者类解耦，解决了目标类和适配者类接口不一致的问题。

其缺点是：
	对类适配器来说，更换适配器的实现过程比较复杂。

类适配器模式可采用多重继承方式实现


# 适配器模式

适配器模式用于转换一种接口适配另一种接口。

实际使用中Adaptee一般为接口，并且使用工厂函数生成实例。

在Adapter中匿名组合Adaptee接口，所以Adapter类也拥有SpecificRequest实例方法，又因为Go语言中非入侵式接口特征，其实Adapter也适配Adaptee接口。



*/
